import axios from "axios";
import type {
  AxiosError,
  AxiosInstance,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from "axios";
import { BASE_URL, SIG } from "@/utils/env";

import { message } from "antd";
import type { EnhancedStore } from "@reduxjs/toolkit";
import type { RootState } from "@/store";
import { isFileOrBlob, sortParams } from "./tool";
import md5 from "md5";

export const instance: AxiosInstance = axios.create({
  baseURL: BASE_URL,
  headers: {
    "Content-Type": "multipart/form-data",
  },
});

// 请求拦截
instance.interceptors.request.use(
  async (
    config: InternalAxiosRequestConfig
  ): Promise<InternalAxiosRequestConfig> => {
    const store: EnhancedStore = await import("@/store").then(
      (module) => module.default
    );
    const state: RootState = store.getState();
    config.headers.Authorization = `${state?.app?.userInfo?.user_token}`;
    return config;
  },
  (error: AxiosError): Promise<AxiosError> => {
    return Promise.reject(error);
  }
);

// 响应拦截
instance.interceptors.response.use(
  (response: AxiosResponse): Promise<AxiosResponse> => {
    const { data } = response;
    if (data?.code == 0) {
      return Promise.resolve(response.data);
    } else {
      if ([997].includes(data?.code)) {
        message.error("Token无效了，请重新登录");
      } else {
        message.error(
          `${data?.msg || ""}-${data?.error || ""}-${data?.data?.msg}-【code:${
            data?.code
          }】`
        );
      }
      return Promise.reject(data);
    }
  },
  (error: AxiosError): Promise<AxiosError> => {
    message.error(error.message);
    return Promise.reject(error);
  }
);

type NewParams =
  | {
      [key: string]: any;
    }
  | FormData;
type Method = "get" | "post" | "put" | "delete" | "patch";
export default async function request(
  url: string,
  params: Object | FormData,
  method: Method
): Promise<AxiosResponse> {
  const store: EnhancedStore = await import("@/store").then(
    (module) => module.default
  );
  const state: RootState = store.getState();
  const newParams: NewParams = params;
  const sigParams: { [key: string]: any } = {};

  if (newParams instanceof FormData) {
    newParams.append(
      "admin_user_id",
      String(state?.app?.userInfo?.admin_user_id)
    );
    //@ts-ignore
    for (const [key, value] of newParams.entries()) {
      if (!isFileOrBlob(value)) {
        const replaceVal = (value as string).replace(/\r\n/g, "\n");
        sigParams[key] = replaceVal;
        newParams.set(key, replaceVal);
      }
    }
    newParams.append("sig", md5(sortParams(sigParams) + SIG));
  } else {
    newParams.admin_user_id =
      newParams.admin_user_id || state?.app?.userInfo?.admin_user_id;
    for (const key in newParams) {
      sigParams[key] = newParams[key];
      if (typeof newParams[key] === "string") {
        const replaceVal = newParams[key].replace(/\r\n/g, "\n");
        sigParams[key] = replaceVal;
        newParams[key] = replaceVal;
      }
    }
    newParams.sig = md5(sortParams(sigParams) + SIG);
  }
  return instance.request({
    url,
    method,
    data: ["put", "post", "delete", "patch"].includes(
      method.toLocaleLowerCase()
    )
      ? newParams
      : undefined,
    params: !["put", "post", "delete", "patch"].includes(
      method.toLocaleLowerCase()
    )
      ? newParams
      : undefined,
  });
}
